#pragma once
#include "../Util/util.hpp"
#include <unordered_map>
#include <memory>

typedef enum {UNLOGIN, LOGIN} ss_status;
class session
{
private:
    uint64_t _ssid; 
    uint64_t _uid;
    ss_status _status;
    wsserver_t::timer_ptr _tp;
public:
    session(uint64_t ssid)
    :_ssid(ssid),_status(UNLOGIN)
    {
        LOG(INFO) << "创建session成功" << "\n";
    }
    ~session()
    {
        LOG(INFO) << "销毁session成功" << "\n";
    }
    uint64_t get_ssid()
    {
        return _ssid;
    }
    void set_user(uint64_t uid)
    {
        _uid = uid;
    }
    uint64_t get_user()
    {
        return _uid;
    }
    void set_status(ss_status status)
    {
        _status = status;
    }
    bool is_login()
    {
        return (_status == LOGIN);
    }
    void set_timer(const wsserver_t::timer_ptr& tp)
    {
        _tp = tp;
    }
    wsserver_t::timer_ptr get_timer()
    {
        return _tp;
    }
};


#define FIXTIME 20000
#define FOREVER -1
typedef std::shared_ptr<session> session_ptr;
class session_manager
{
private:
    uint64_t _ssid;
    std::mutex _mutex;
    std::unordered_map<uint64_t, session_ptr> _session;
    wsserver_t* _server;
public:
    session_manager(wsserver_t* server)
    :_server(server),_ssid(1)
    {
        LOG(INFO) << "创建session管理成功" << "\n";
    }
    ~session_manager()
    {
        LOG(INFO) << "销毁session管理成功" << "\n";
    }
    session_ptr create_session(uint64_t uid, ss_status status)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        session_ptr sp(new session(_ssid));
        sp->set_status(status);
        sp->set_user(uid);
        _session.insert({_ssid, sp});
        _ssid++;
        return sp;
    }   
    session_ptr get_session_by_ssid(uint64_t ssid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _session.find(ssid);
        {
            if(it == _session.end())
            {
                return session_ptr();
            }
        }
        return it->second;
    }
    void append_session(session_ptr& sp)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _session.insert({sp->get_ssid(), sp});
    }
    void remove_session(uint64_t ssid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _session.erase(ssid);
    }
    void set_session_expire_time(uint64_t ssid, int ms)
    {
        auto it = _session.find(ssid);
        if(it == _session.end()) return;
        session_ptr sp = it->second;
        wsserver_t::timer_ptr tp = sp->get_timer();
        // 永久-》永久
        if(tp.get() == nullptr && ms == FOREVER)
        {
            return;
        }
        // 永久-》定时
        else if(tp.get() == nullptr && ms != FOREVER)
        {
            wsserver_t::timer_ptr tmp_tp = _server->set_timer(ms, 
                std::bind(&session_manager::remove_session, this, ssid));
            sp->set_timer(tmp_tp);
        }
        // 定时-》永久
        else if(tp.get() != nullptr && ms == FOREVER)
        {
            tp->cancel();
            sp->set_timer(wsserver_t::timer_ptr());
            _server->set_timer(0, std::bind(&session_manager::append_session, this, sp));
        }
        // 定时-》定时(重置时间)
        else 
        {
            tp->cancel();
            sp->set_timer(wsserver_t::timer_ptr());
            _server->set_timer(0, std::bind(&session_manager::append_session, this, sp));

            wsserver_t::timer_ptr tmp_tp = _server->set_timer(ms, 
                std::bind(&session_manager::remove_session, this, sp->get_ssid()));
            sp->set_timer(tmp_tp);
        }
    }
};